#include "respond.h"
#include <string.h>
#include "log.h"

#define BUF_SIZE 9999

int process_method(char a[])
{
    if (strcmp(a, GET) == 0)
        return STATE_GET;
    if (strcmp(a, HEAD) == 0)
        return STATE_HEAD;
    if (strcmp(a, POST) == 0)
        return STATE_POST;
    return STATE_UNKNOW;
}

int match_version(char a[])
{
    if (strcmp(a, "HTTP/1.1") == 0)
        return 0;
    return 1;
}

Respond *init_respond()
{
    Respond *respond = (Respond *)malloc(sizeof(Respond));
    respond->content_length = 0;
    respond->header_count = 0;
    respond->type = 0;
    return respond;
}

void respond_400(Respond *respond)
{
    strcpy(respond->respond_line, "HTTP/1.1 400 Bad request\r\n");
}

void respond2buf(Respond *respond, char *buf)
{
    int i;
    strcpy(buf, respond->respond_line);
    // int count=respond->header_count;
    if (respond->header_count != 0)
    {
        for (i = 0; i < respond->header_count; i++)
            strcat(buf, respond->headers[i].header_value);
    }
    strcat(buf, "\r\n");
    if (respond->content_length != 0)
    {
        // printf("%d\n",respond->content_length);
        strcat(buf, respond->message_body);
    }
}

void respond_505(Respond *respond)
{
    strcpy(respond->respond_line, "HTTP/1.1 505 HTTP Version not supported\r\n");
}

void respond_501(Respond *respond)
{
    strcpy(respond->respond_line, "HTTP/1.1 501 Not Implemented\r\n");
}

int file_status(char PATH[], int client_sock)
{
    struct stat buf;
    int status = stat(PATH, &buf);
    switch (status)
    {
    case 0:
        return 0;
        break;
    case 2:
        LOG_PRINT(LOG_ERROR, " [client %d]\r\n\t[404 Not Found]  %s: No such file or directory", client_sock, PATH);
        LOG_Destroy();
        return 2;
        break;
    case 20:
        LOG_PRINT(LOG_ERROR, " [client %d]\r\n\t[404 Not Found]  %s:  Not a directory", client_sock, PATH);
        LOG_Destroy();
        return 20;
        break;
    case 13:
        LOG_PRINT(LOG_ERROR, " [client %d]\r\n\t[404 Not Found]  %s: Permission denied", client_sock, PATH);
        LOG_Destroy();
        return 13;
        break;
    case 12:
        LOG_PRINT(LOG_ERROR, " [client %d]\r\n\t[404 Not Found]  %s:  Out of memory ", client_sock, PATH);
        LOG_Destroy();
        return 12;
        break;
    default:
        LOG_PRINT(LOG_ERROR, " [client %d]\r\n\t[404 Not Found]  %s:  File unknown error ", client_sock, PATH);
        LOG_Destroy();
        return 1;
        break;
    }
}

void respond_404(Respond *respond)
{
    strcpy(respond->respond_line, "HTTP/1.1 404 Not Found\r\n");
}

void respond_GET_200(Respond *respond, char PATH[])
{
    // strcpy(respond->respond_line, "HTTP/1.1 200 OK\r\n");
    respond_HEAD_200(respond, PATH);
    FILE *pfile;
    if (respond->type == 'r')
        pfile = fopen(PATH, "r");
    else
        pfile = fopen(PATH, "rb");
    fseek(pfile, 0, SEEK_END);
    int length = ftell(pfile);
    rewind(pfile);
    length = fread(respond->message_body, 1, length, pfile);
    respond->message_body[length] = '\0';
    fclose(pfile);
    respond->content_length = length + 1;
}

void respond_HEAD_200(Respond *respond, char PATH[])
{
    strcpy(respond->respond_line, "HTTP/1.1 200 OK\r\n");

    respond->header_count = 6;
    respond->headers = (Respond_headers *)malloc(sizeof(Respond_headers) * respond->header_count);
    char head[4096];
    memset(head, 0, 4096);
    char buffer[80];
    memset(buffer, 0, 80);
    struct stat buf;
    stat(PATH, &buf);

    if (buf.st_mode & S_IFCHR == S_IFCHR)
        respond->type = 'r';
    else
        respond->type = 'b';

    strcpy((respond->headers)[0].header_value, "Server: Liso/1.0\r\n");

    time_t rawtime;
    struct tm *info;
    time(&rawtime);
    info = localtime(&rawtime);
    strftime(buffer, 80, "%a, %d %b %y %X %Z", info);
    sprintf(head, "Date: %s\r\n", buffer);
    strcpy((respond->headers)[1].header_value, head);
    // free(info);
    memset(buffer, 0, 80);
    memset(head, 0, 4096);

    sprintf(head, "Content-Length: %ld\r\n", buf.st_size);
    strcpy((respond->headers)[2].header_value, head);
    memset(head, 0, 4096);

    char suffix[40];
    strcpy(suffix, strrchr(PATH, '.'));

    char type[20];
    memset(type, 0, 20);
    if (respond->type == 'r')
        strcpy(type, "text");
    else
    {
        if (ident_type(suffix+1) == IMAGE)
            strcpy(type, "image");
    }

    sprintf(head, "Content-type: %s/%s\r\n", type, suffix + 1);
    strcpy((respond->headers)[3].header_value, head);

    struct tm *p;
    p = gmtime(&(buf.st_mtime));
    strftime(buffer, 80, "%a, %d %b %y %X %Z", p);
    sprintf(head, "Last-modified: %s\r\n", buffer);
    strcpy((respond->headers)[4].header_value, head);
    // free(p);
    memset(buffer, 0, 80);
    memset(head, 0, 4096);

    strcpy((respond->headers)[5].header_value, "Connection: keep-alive\r\n");

    memset(head, 0, 4096);
}

void free_respond(Respond *respond)
{
    if (respond->headers!=NULL)
        free(respond->headers);
    free(respond);
}

int ident_type(char *suffix)
{
    if (!strcmp(suffix, "png") || !strcmp(suffix, "jpeg") || !strcmp(suffix, "jpg") || !strcmp(suffix, "gif") || !strcmp(suffix, "bmp"))
        return IMAGE;
}